#pragma once

#include <iostream>
#include <string>
#include <memory>
#include "Socket.hpp"
#include <jsoncpp/json/json.h>
#include "Log.hpp"
#include <functional>

using namespace LogModule;
using namespace SocketModule;

// 实现一个自定义的网络版本的计算器

// 约定好各个字段的含义，本质就是约定好协议
// 使用现成的方式做序列化和反序列话 -- Json
// client -> server
class Request
{
public:
    Request() {}
    Request(int x, int y, char oper)
        : _x(x),
          _y(y),
          _oper(oper)
    {
    }

    // 序列化
    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper; // _oper是 char，也是整数，序列化后字符串中为其ASCII码值

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }

    // 反序列化
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;

        bool ok = reader.parse(in, root);

        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }

        return ok;
    }

    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _oper; }
    ~Request() {}

private:
    int _x;
    int _y;
    char _oper;
};

// server -> client
class Response
{
public:
    Response() {}
    Response(int result, int code)
        : _result(result),
          _code(code)
    {
    }

    // 序列化
    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        return writer.write(root);
    }

    // 反序列化
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);

        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }

        return ok;
    }

    void SetResult(int res)
    {
        _result = res;
    }

    void SetCode(int code)
    {
        _code = code;
    }

    void ShowResult()
    {
        std::cout << "计算结果: " << _result << "[" << _code << "]" << std::endl;
    }

    ~Response() {}

private:
    int _result; // 运算结果
    int _code;   // 0:success, 1,2,3,4->不同运算异常情况
};

// 期望的一个完整报文: 50\r\n{"x" : 10, "y" : 20, "oper" : '+'}\r\n -- 头部表示该报文有效载荷的长度

const std::string sep = "\r\n";
using func_t = std::function<Response(Request &req)>; // 服务器上层应用回调函数

class Protocol
{
public:
    Protocol() {}
    Protocol(func_t func) : _func(func)
    {
    }

    // 应用层封装报头
    std::string Encode(const std::string &jsonstr)
    {
        // 50\r\n{"x" : 10, "y" : 20, "oper" : '+'}\r\n
        std::string len = std::to_string(jsonstr.size());
        return len + sep + jsonstr + sep;
    }

    // 应用层解析报文
    // 1. 判断报文完整性
    // 2. 如果包含至少一个有效报文，提取它并移出它
    bool Decode(std::string &buffer, std::string *package)
    {
        ssize_t pos = buffer.find(sep);
        if (pos == std::string::npos)
            return false;
        std::string package_len_str = buffer.substr(0, pos);                        // 字符串类型的有效载荷的长度
        int package_len_int = std::stoi(package_len_str);                           // int 类型的有效载荷的长度
        int target_len = package_len_str.size() + package_len_int + 2 * sep.size(); // 完整报文的长度
        if (buffer.size() < target_len)
            return false;

        *package = buffer.substr(pos + sep.size(), package_len_int);
        buffer.erase(0, target_len);
        return true;
    }

    // 服务端获取请求，处理后并发送
    void GetRequest(std::shared_ptr<Socket> &sock, InetAddr &client)
    {
        std::string buffer_queue;
        while (true)
        {
            // 1. 从网络中读取数据
            int n = sock->Recv(&buffer_queue);
            if (n > 0)
            {
                std::string json_package;
                // 2. 解析报文，提取完整的一个请求，如果不完整，让服务器继续读取
                // bool ret = Decode(buffer_queue, &json_package);
                // if (!ret)
                //     continue;

                while (Decode(buffer_queue, &json_package))
                {
                    LOG(LogLevel::DEBUG) << client.StringAddr() << " 请求: " << json_package;
                    // 3. 请求 Json 串反序列化
                    Request req;
                    bool ok = req.Deserialize(json_package);
                    if (!ok)
                        continue;

                    // 4. 通过回调函数将请求处理为回应 -- 业务
                    Response resp = _func(req);

                    // 5. 序列化 -- 将回应结构体数据转化为序列字符串
                    std::string json_str = resp.Serialize();

                    // 6. 添加报头构成完整报文
                    std::string send_str = Encode(json_str);

                    // 7. 发送
                    sock->Send(send_str);
                }
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "client: " << client.StringAddr() << " quit!";
                break;
            }
            else
            {
                LOG(LogLevel::WARNING) << "client: " << client.StringAddr() << ", recv error";
                break;
            }
        }
    }

    // 客户端获取应答
    bool GetResponse(std::shared_ptr<Socket> &client, std::string &resp_buf, Response *resp)
    {
        while (true)
        {
            int n = client->Recv(&resp_buf);
            if (n > 0)
            {
                std::string json_package;
                while (Decode(resp_buf, &json_package))
                {
                    resp->Deserialize(json_package);
                }
                return true;
            }
            else if (n == 0)
            {
                std::cout << "server quit " << std::endl;
                return false;
            }
            else
            {
                std::cout << "recv error" << std::endl;
                return false;
            }
        }
    }
    ~Protocol()
    {
    }

private:
    func_t _func;
};